using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Contexts;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace ComponentEngine_12_12_2014 {

	public class MyGame : Game {

		private GraphicsDeviceManager Graphics;
		public static SpriteBatch SpriteBatch;

		public static GameTime GameTime;
		private static int NumEntities = 100;
		private Entity[] Entities = new Entity[NumEntities];

		// TODO: Texture Atlas
		private Texture2D ZombieIdleTexture;
		private Texture2D PaintingSunnyField1Texture;
		private Texture2D ArrowTexture;
		private Texture2D StoneFloorTexture;
		private Texture2D RedTexture;
		private Texture2D YellowTexture;
		private Texture2D GreenTexture;
		private Texture2D Alarm1Texture;
		private Texture2D Alarm2Texture;

		private KeyboardState PreviousKeyboardState;
		private KeyboardState CurrentKeyboardState;

		private Dictionary<string, Animation> Animations; 


		public MyGame() {
			Graphics = new GraphicsDeviceManager(this);
			Content.RootDirectory = "Content";
			Graphics.PreferredBackBufferWidth = 1280;
			Graphics.PreferredBackBufferHeight = 720;
			Animations = new Dictionary<string, Animation>();
		}


		protected override void Initialize() {
			// TODO: Add your initialization logic here

			base.Initialize();
		}


		protected override void LoadContent() {
			SpriteBatch = new SpriteBatch(GraphicsDevice);

			ZombieIdleTexture = Content.Load<Texture2D>("Zombie_Idle");
			PaintingSunnyField1Texture = Content.Load<Texture2D>("Painting_SunnyField_1");
			ArrowTexture = Content.Load<Texture2D>("Arrow");
			StoneFloorTexture = Content.Load<Texture2D>("Stone_Floor");
			RedTexture = Content.Load<Texture2D>("Red");
			YellowTexture = Content.Load<Texture2D>("Yellow");
			GreenTexture = Content.Load<Texture2D>("Green");
			Alarm1Texture = Content.Load<Texture2D>("Alarm_1");
			Alarm2Texture = Content.Load<Texture2D>("Alarm_2");

			Animations.Add("Sensor_Idle", new Animation {
				Frames = new[] {RedTexture, YellowTexture, GreenTexture},
				FrameSeconds = new float[]{1, 2, 3},
				NumFrames = 3
			});
			Animations.Add("Sensor_Alarmed", new Animation {
				Frames = new[] {Alarm1Texture, Alarm2Texture},
				FrameSeconds = new []{.25f, .25f},
				NumFrames = 2
			});

			// Load Level
			int index = 0;
			Vector2 position;
			Vector2 origin;

			//=====( Begin Decorations )====================

			Entities[index] = new Entity {
				Index = index,
				IsActive = true,
				Position = new Vector2(400),
				HasAppearance = true,
				Texture = PaintingSunnyField1Texture,
				Color = Color.White
			};
			index++;

			//-----

			position = new Vector2(868, 400);
			origin = new Vector2(ArrowTexture.Width/2f, ArrowTexture.Height/2f);
			position += origin;
			Entities[index] = new Entity {
				Index = index,
				Name = "Left_Arrow",
				IsActive = true,
				Position = position,
				HasAppearance = true,
				Texture = ArrowTexture,
				Color = Color.White,
				Rotation = MathHelper.ToRadians(270),
				Origin = origin
			};
			index++;

			//-----

			position = new Vector2(900, 368);
			origin = new Vector2(ArrowTexture.Width/2f, ArrowTexture.Height/2f);
			position += origin;
			Entities[index] = new Entity {
				Index = index,
				Name = "Up_Arrow",
				IsActive = true,
				Position = position,
				HasAppearance = true,
				Texture = ArrowTexture,
				Color = Color.White,
				Rotation = MathHelper.ToRadians(0),
				Origin = origin
			};
			index++;

			//-----

			position = new Vector2(932, 400);
			origin = new Vector2(ArrowTexture.Width/2f, ArrowTexture.Height/2f);
			position += origin;
			Entities[index] = new Entity {
				Index = index,
				Name = "Right_Arrow",
				IsActive = true,
				Position = position,
				HasAppearance = true,
				Texture = ArrowTexture,
				Color = Color.White,
				Rotation = MathHelper.ToRadians(90),
				Origin = origin
			};
			index++;

			//-----

			position = new Vector2(900, 432);
			origin = new Vector2(ArrowTexture.Width/2f, ArrowTexture.Height/2f);
			position += origin;
			Entities[index] = new Entity {
				Index = index,
				Name = "Down_Arrow",
				IsActive = true,
				Position = position,
				HasAppearance = true,
				Texture = ArrowTexture,
				Color = Color.White,
				Rotation = MathHelper.ToRadians(180),
				Origin = origin
			};
			index++;

			//-----

			Entities[index] = new Entity {
				Index = index,
				Name = "Sensor",
				IsActive = true,
				Position = new Vector2(300, 400),
				GeneralState = GeneralState.Idle,
				HasAnimation = true,
				GeneralStateAnimations = new Dictionary<GeneralState, Animation> {
					{GeneralState.Idle, Animations["Sensor_Idle"]},{GeneralState.Alarmed, Animations["Sensor_Alarmed"]}
				},
				Animation = Animations["Sensor_Idle"],
				HasAppearance = true,
				Color = Color.White
			};
			index++;

			//=====( End Decorations )======================
			////////////////////////////////////////////////
			//=====( Begin Props )==========================

			int textureWidth = StoneFloorTexture.Width;
			for (int i = 0; i < 10; i++) {
				Entities[index] = new Entity {
					Index = index,
					Name = "Stone_Floor " + i,
					IsActive = true,
					Position = new Vector2(textureWidth*i, 500),
					HasAppearance = true,
					Texture = StoneFloorTexture,
					Color = Color.White
				};
				index++;
			}

			//-----

			//=====( End Props )============================
			////////////////////////////////////////////////
			//=====( Begin Actors )=========================

			Entities[index] = new Entity {
				Index = index,
				Name = "Zombie 1",
				IsActive = true,
				Position = new Vector2(300, 500 - 64),
				HasMind = true,
				MindType = MindType.Enemy,
				HasMovement = true,
				MovementState = MovementState.Idle,
				Speed = 50,
				HorizontalDirection = HorizontalDirection.Right,
				HasAppearance = true,
				Texture = ZombieIdleTexture,
				Color = Color.White
			};
			index++;

			//=====( End Actors )===========================
		}


		protected override void UnloadContent() {
			// TODO: Unload any non ContentManager content here
		}


		protected override void Update(GameTime gameTime) {
			GameTime = gameTime;

			PreviousKeyboardState = CurrentKeyboardState;
			CurrentKeyboardState = Keyboard.GetState();
			if (CurrentKeyboardState.IsKeyDown(Keys.Escape)) {
				Exit();
			}
			if (CurrentKeyboardState.IsKeyDown(Keys.S) && PreviousKeyboardState.IsKeyUp(Keys.S)) {
				// TODO: In the real game, when the state changes, the animation changes.
				Entity e = Entities.Where(x => x.Name == "Sensor").Single();
				if (e.GeneralState == GeneralState.Idle) {
					e.GeneralState = GeneralState.Alarmed;
					e.Animation = e.GeneralStateAnimations[GeneralState.Alarmed];
				} else if (e.GeneralState == GeneralState.Alarmed) {
					e.GeneralState = GeneralState.Idle;
					e.Animation = e.GeneralStateAnimations[GeneralState.Idle];
				}
				Entities[e.Index] = e; // TODO: Are these structs worth it? Pros? Cons?
			}

			for (int i = 0; i < NumEntities; i++) {
				Entities[i].Update();
			}

			base.Update(gameTime);
		}


		protected override void Draw(GameTime gameTime) {
			GraphicsDevice.Clear(new Color(40, 30, 25, 255));

			SpriteBatch.Begin();
			for (int i = 0; i < NumEntities; i++) {
				Entities[i].Draw();
			}
			SpriteBatch.End();

			base.Draw(gameTime);
		}

	}

}